package com.ofek.eventos.net.ocsf.client;

import java.io.IOException;

import com.ofek.eventos.net.Request;
import com.ofek.eventos.net.ServiceCallBack;

public class RemoteService {
	private interface Invokeable<T> {
		public Object invoke(T t);
	}
	private final int port;
	private final String host;

	public RemoteService(final String host,final int port) {
		this.host = host;
		this.port = port;
	}
	protected final Object invoke(final Invokeable<Client> invokeIt) throws IOException {
		final Client client = new Client(host, port); 
		try {
			client.openConnection();
			return invokeIt.invoke(client);
		} finally {
			try {
				client.closeConnection();
			} catch (final IOException e) {
				e.printStackTrace();
			}
		}

	}
	protected void invoke(final Object... params) throws IOException {
		invoke(new Invokeable<Client>() {
			@Override
			public Object invoke(final Client client) {
				final Request request = new Request(getCallerName(),params);
				client.sendAndForget(request);
				return null;
			}
		});
	}
	protected String getCallerName() {
		String methodName = Thread.currentThread().getStackTrace()[0].getMethodName();
		int i;
		for ( i = 1 ; !methodName.equals("handle"); i++ ) methodName = Thread.currentThread().getStackTrace()[i].getMethodName();
		for (  ; methodName.equals("handle"); i++ ) methodName = Thread.currentThread().getStackTrace()[i].getMethodName();
		return methodName;
	}
	protected Object handle(final Object... params) throws IOException {
		return invoke(new Invokeable<Client>() {
			@Override
			public Object invoke(final Client client) {
				final Request request = new Request(getCallerName(),params);
				return client.sendSync(request);
			}
		});
	}

	protected void invoke(final ServiceCallBack scb,final Object... params) throws IOException {
		final Client client = new Client(host, port); 
		client.openConnection();
		final Request request = new Request(getCallerName(),params);
		client.sendToServer(new ServiceCallBack() {

			@Override
			public void onResult(final Object result) {
				try {
					scb.onResult(result);
				} finally {
					try {
						client.closeConnection();
					} catch (final IOException e) {
						e.printStackTrace();
					}
				}

			}

			@Override
			public void onError(final Object error) {
				try {
					scb.onError(error);
				} finally {
					try {
						client.closeConnection();
					} catch (final IOException e) {
						e.printStackTrace();
					}
				}
			}
		}, request);

	}


}
